Some times, you want to plot the 3d-surfaces from freesurfer. Here, it is easier to use data from freesurfer (like annot and colorlut files) to create colours for the vectors. The data is somewhat more complex than the 2d ggplot polygon version ggseg ggseg3d() will create a plotly plot, which is interactive, and provides another type of flexibility to the user. A lot of credit goes to A.M.Winkler and his Brainder work, which supplied us with the first examples of going from .srf to .ply files, and whose scripts massively aided us in making this work.
The function ggseg3d(), is based in the plotly, it is recommended to get a little familiarized with with plotly.
Out-of-the-box, ggseg() works without supplying any extra information. It will create a base plot of the aparc (dkt) brain segmentations. All [...]_3d atlases have a built in colour column for default colour plotting of the segments.
The data is stored in tibbles, and looks like so:
## # A tibble: 6 x 4
## atlas surf hemi ggseg_3d
## <chr> <chr> <chr> <list>
## 1 dkt_3d inflated left <tibble [36 × 8]>
## 2 dkt_3d inflated right <tibble [36 × 8]>
## 3 dkt_3d LCBC left <tibble [36 × 8]>
## 4 dkt_3d LCBC right <tibble [36 × 8]>
## 5 dkt_3d white left <tibble [36 × 8]>
## 6 dkt_3d white right <tibble [36 × 8]>
To grab all the data for a surface and hemisphere, you should reduce the data to one line, and then unnest()
## # A tibble: 36 x 11
## atlas surf hemi area colour mesh label roi annot acronym lobe
## <chr> <chr> <chr> <chr> <chr> <list> <chr> <chr> <chr> <chr> <chr>
## 1 dkt_3d infla… right <NA> <NA> <name… rh_med… 0001 medial… mdlw <NA>
## 2 dkt_3d infla… right banks … #1964… <name… rh_ban… 0002 bankss… bnst temp…
## 3 dkt_3d infla… right caudal… #7D64… <name… rh_cau… 0003 caudal… cdac fron…
## 4 dkt_3d infla… right caudal… #6419… <name… rh_cau… 0004 caudal… cdmf fron…
## 5 dkt_3d infla… right corpus… <NA> <name… rh_cor… 0005 corpus… cc <NA>
## 6 dkt_3d infla… right cuneus #DC14… <name… rh_cun… 0006 cuneus cuns occi…
## 7 dkt_3d infla… right entorh… #DC14… <name… rh_ent… 0007 entorh… entr temp…
## 8 dkt_3d infla… right fusifo… #B4DC… <name… rh_fus… 0008 fusifo… fsfr temp…
## 9 dkt_3d infla… right inferi… #DC3C… <name… rh_inf… 0009 inferi… infp pari…
## 10 dkt_3d infla… right inferi… #B428… <name… rh_inf… 0010 inferi… inft temp…
## # … with 26 more rows
Particularly notice the mesh column, which is a list column of lists. In there is all the 6 vectors needed to create the mesh of the tri-surface plot. You’ll also need to notive the label, annot and area columns, which are likely the columns you will be matching on when proviging with your own data for colours. You need to be meticulous when fixing your data, be sure it matches. The function should give you a warning if it’s struggling to match something.
The column you want to use for colour, needs to be supplied to the colour option, and you’ll likely want to supply it to the text option, as this will add another line to the plotly hover information.
someData = dkt_3d %>%
filter(surf == "inflated" & hemi == "right") %>%
unnest(ggseg_3d) %>%
select(area) %>%
na.omit() %>%
mutate(p = sample(seq(0,.5, length.out = 100 ), nrow(.)) %>%
round(2))
ggseg3d(.data = someData,
atlas = dkt_3d,
colour = "p", text = "p") %>%
pan_camera("right medial")## values norm orig hex
## 1 0.01 0 skyblue #87CEEB
## 2 0.47 1 dodgerblue #1E90FF
You can provide custom colour palettes either in hex or R-names
ggseg3d(.data = someData, atlas = dkt_3d,
colour = "p", text = "p",
palette = c("forestgreen", "white", "firebrick"))A new improvement now allows you to also supply a named vector as palette, to control the breakpoints of the palette values, and allow you to have a colour bar that exceeds the values that exist in the data plotted.
ggseg3d(.data = someData, atlas = dkt_3d,
colour = "p", text = "p",
palette = c("forestgreen" = 0, "white" = .05, "firebrick" = 1))## values norm orig hex
## 1 0.00 0.00 forestgreen #228B22
## 2 0.05 0.05 white #FFFFFF
## 3 1.00 1.00 firebrick #B22222
If you are plotting the sub-cortical structures, you might want to reduce the opacity of the NA structures, so that you can see the more medial structures. you may also want to add the glassbrain.
somData_aseg = aseg_3d %>%
unnest(cols = ggseg_3d) %>%
select(label) %>%
filter(!grepl("Ventricle|Putamen|Amygdala", label)) %>%
mutate(p = seq(1, nrow(.)))
ggseg3d(.data = somData_aseg, atlas = aseg_3d,
colour = "p", text = "p",
na.alpha= .5) %>%
add_glassbrain()## values norm orig hex
## 1 1 0 skyblue #87CEEB
## 2 24 1 dodgerblue #1E90FF